#include "HMC5983.h"
#include "_I2C_.h"
/*
如果要移植的话不喜欢我的iic，可以换成你自己的只需把
I2C(HMC5983_I2C)->Write_Reg(reg,data)换成你自己的IIC写寄存器的函数即可
*/
I2C_BUS HMC5983_I2C;
#define HMC5983Wirte_Reg(reg,data) I2C(HMC5983_I2C)->Write_Reg(reg,data)//可以替换为你的写寄存器函数
#define HMC5983Read_Reg(reg)    I2C(HMC5983_I2C)->Read_Reg(reg)//可以替换为你的读寄存器函数

/////////////////////////////////////寄存器///////////////////////////////////////////
#define RegisterA 0x00
#define RegisterB 0x01
#define ModeReg   0x02
#define X_MSB     0x03
#define X_LSB     0x04
#define Z_MSB     0x05
#define Z_LSB     0x06
#define Y_MSB     0x07
#define Y_LSB     0x08
#define StatusReg 0x09
#define Identifiction_regA 0x0A
#define Identifiction_regB 0x0B
#define Identifiction_regC 0x0C
#define Temp_MSB 0x31
#define Temp_LSB 0x32

//////////////////////////////////以下操作是参数选择/////////////////////////////////////////////
typedef enum{//采样求平均
    Sample_1 = 0x00,
    Sample_2 = 0x20,
    Sample_4 = 0x40,
    Sample_8 = 0x60
}Sample_Avr_TypeDef;

typedef enum{
    UltraSlow = 0x00,//0.75hz
    SuperSlow = 0x04,//1.5hz
    Slow  = 0x08,//3hz
    Mediun = 0x10,//15hz
    Fast = 0x14,//30hz
    SuperFast = 0x18,//75hz
    UltraFast = 0x1C//220hz
}Rate_TypeDef;

typedef enum{
    Normal = 0x00,//正常模式
    Positive = 0x01,
    Negative =  0x02,
    Temp_Only = 0x03//只打开温度计 oepn temperature sensor only
}MS_TypeDef;

typedef enum{
    Ga_0_88 = 0x00,//用于0.88Ga的磁场范围，这意味着这个是增益最大的
    GA_1_3 = 0x20,
    Ga_1_9 = 0x40,
    Ga_2_5 = 0x60,
    Ga_4_0 = 0x80,
    Ga_4_7 = 0xA0,
    Ga_5_6 = 0xC0,
    Ga_8_1 = 0xE0//用于8.1Ga的磁场测量范围，增益最小的
}Gain_TypeDef;//增益

//////////////////////////////////以下操作是参数选择/////////////////////////////////////////////
//可以|上下列模式，如 Continue|HighSpeed_I2C 高速I2C以及连续转换模式
#define   HighSpeed_I2C 0x80//高速SPI模式 
#define   LowPowerMode 0x20//低功耗模式
typedef enum{
    Continue = 0x00,//连续转换
    Single = 0x01,//单次触发
    Idle = 0x02//空闲模式
}Mode_TypeDef;

typedef enum{
    Temp_DISABLE = 0x00,//连续转换
    Temp_ENABLE = 0x80
}Temp_TypeDef;

typedef struct RegAInitTypedef{//寄存器A的结构体
    Temp_TypeDef Temp_EN;               //@ref to Temp_TypeDef 查阅此处枚举
    Sample_Avr_TypeDef Sample_ave;      //@ref to Sample_Avr_TypeDef 查阅此处枚举
    Rate_TypeDef Rate;                  //@ref to Rate_TypeDef 查阅此处枚举
    MS_TypeDef MS_Mode;                 //@ref to MS_TypeDef 查阅此处枚举
}RegAInitTypedef;

typedef struct RegBInitTypedef{//寄存器B的结构体
    Gain_TypeDef Gain_Set;
}RegBInitTypedef;

typedef struct HMCModeReg{//寄存器C的结构体
    Mode_TypeDef Mode_Set;
}HMCModeReg;

static void HMC5983_REG_Init(RegAInitTypedef* RegA,RegBInitTypedef* RegB,HMCModeReg* Mode_reg){
	uint8_t input_reg = RegA->MS_Mode|RegA->Rate|RegA->Sample_ave|RegA->Temp_EN;
	HMC5983Wirte_Reg(RegisterA,input_reg);
	input_reg = RegB->Gain_Set;
	HMC5983Wirte_Reg(RegisterB,input_reg);
	input_reg = Mode_reg->Mode_Set;
	HMC5983Wirte_Reg(ModeReg,input_reg);
}
///////////////////////////////////////以上代码为底层不用看////////////////////////////////////////////////////


static int16_t calibration_x = 0;
static int16_t calibration_y = 0;
/////////////////////////User//////////////////////////////////
void HMC5983_Init(GPIO_TypeDef* GPIOx,uint16_t SCL,uint16_t SDA){
	HMC5983_I2C = Create_SI2C(GPIOx,SCL,SDA,HMC5983_Address);//初始化软件IIC结构体

	//与STM32标准库异曲同工
	struct RegAInitTypedef MYregA;//寄存器A：正常模式+快速+8次采样+打开温度计
	MYregA.MS_Mode = Normal;
	MYregA.Rate = Fast;
	MYregA.Sample_ave = Sample_8;
	MYregA.Temp_EN = Temp_ENABLE;//打开温度计可以，打开温度补偿，提升磁力计的精度
	
	struct RegBInitTypedef MYregB;//寄存器B:测2.5Ga磁场，一般增益
	MYregB.Gain_Set = Ga_8_1;

	struct HMCModeReg MYModereg;//模式选择:连续模式
	MYModereg.Mode_Set = Continue;

	HMC5983_REG_Init(&MYregA,&MYregB,&MYModereg);
}

void HMC5983_Get_Data(HMC5983_Typedef* HMC5893_ptr){
	HMC5893_ptr->XMag = (HMC5983Read_Reg(X_MSB)<<8)|HMC5983Read_Reg(X_LSB);
	HMC5893_ptr->YMag = (HMC5983Read_Reg(Y_MSB)<<8)|HMC5983Read_Reg(Y_LSB);
	HMC5893_ptr->ZMag = (HMC5983Read_Reg(Z_MSB)<<8)|HMC5983Read_Reg(Z_LSB);
}

float HMC5983_Get_temp(void){
	//记得先打开温度计 remenber to enable your temparature register at first
	int16_t temp = (HMC5983Read_Reg(Temp_MSB)<<8) + HMC5983Read_Reg(Temp_LSB);
	return (float)temp/128 + 25;
}

float HMC5983_Get_Angle(void){
	static struct HMC5983 HMC;
	float angle=0;
	HMC5983_Get_Data(&HMC);
	float raw_angle = (float)(HMC.YMag - calibration_y)/(float)(HMC.XMag -calibration_x);
	if(HMC.XMag > 0 && HMC.YMag > 0)angle = atan(raw_angle)*180 / 3.141592f;
	else if(HMC.XMag > 0 && HMC.YMag < 0)angle = 360 + atan(raw_angle)*180 / 3.141592f;
	else if(HMC.XMag == 0 && HMC.YMag > 0)angle = 90;
	else if(HMC.XMag == 0 && HMC.YMag < 0)angle = 270;
	else if(HMC.XMag < 0 )angle = 180 + atan(raw_angle)*180/3.141592f;
	if(angle>360)angle=360;
	if(angle<0)angle=0;

	return angle;//如果返回了999那么是错误数据
}

void HMC5983_calibration(void){
	struct HMC5983 HMC;
	uint8_t i =0;
	int16_t XGaMax=0;
	int16_t YGaMax=0;
	int16_t XGaMin=0;
	int16_t YGaMin=0;
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
	while (i!=200)//采集200个点
	{
		HMC5983_Get_Data(&HMC);
		XGaMax = XGaMax < HMC.XMag? HMC.XMag:XGaMax;//找X的最大值
		XGaMin = XGaMin > HMC.XMag? HMC.XMag:XGaMin;//找X的最小值
		YGaMax = YGaMax < HMC.YMag? HMC.YMag:YGaMax;//找Y的最大值
		YGaMin = YGaMin > HMC.YMag? HMC.YMag:YGaMin;//找Y的最小值
		Delay_ms(50);//50*200 10s后结束采样
		i++;
	}
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
	calibration_x = (XGaMax + XGaMin)/2;
	calibration_y = (YGaMax + YGaMin)/2;
}

uint8_t HMC5983_Status(void){
	uint8_t temp = HMC5983Read_Reg(StatusReg);

	/*2事件发生条件，注意：数据在3和1之间发生跳变很正常，因为满足条件2(1)
		1.all six bytes have been read and the next measurement 
		starts, 
		2. The mode register is written, 
		3. The measurement configuration (CRA) is written,
		4. Power is reset.
	*/
	return temp;//如果返回3说明12事件都发生
}


uint8_t HMC5983_RegA_ID(void){
	return HMC5983Read_Reg(Identifiction_regA);
}

uint8_t HMC5983_RegB_ID(void){
	return HMC5983Read_Reg(Identifiction_regB);
}

uint8_t HMC5983_RegC_ID(void){
	return HMC5983Read_Reg(Identifiction_regC);
}
